package com.example.utility.crypto.aes;

import javax.crypto.Cipher;
import javax.crypto.KeyGenerator;
import javax.crypto.SecretKey;
import javax.crypto.spec.SecretKeySpec;
import java.util.Base64;

/**
 * @author 季舟
 * @Date 2024-12-19 17:18
 */
public class AESDemo {
    public static void main(String[] args) {
        try {
            // 生成AES密钥
            // 密钥长度可选128, 192, 或 256位，此处选择128位
            SecretKey secretKey = generateKey(128);
            // 将生成的密钥转换为Base64编码，以便安全传输和存储
            String secretKeyBase64 = Base64.getEncoder().encodeToString(secretKey.getEncoded());
            System.out.println("Generated AES Key (Base64): " + secretKeyBase64);

            // 要加密的数据
            String originalData = "Hello, AES Signature!";
            System.out.println("Original String: " + originalData);

            // 加密数据
            // 使用之前生成的密钥对原始数据进行加密
            String encryptedData = encrypt(originalData, secretKeyBase64);
            System.out.println("Encrypted String: " + encryptedData);

            // 解密数据
            // 使用同一密钥对加密后的数据进行解密，以验证加密解密的正确性
            String decryptedString = decrypt(encryptedData, secretKeyBase64);
            System.out.println("Decrypted String: " + decryptedString);

        }catch (Exception e){
            // 异常处理块，可根据实际需求添加日志记录或错误处理逻辑
            e.printStackTrace();
        }
    }

    /**
     * 生成AES密钥
     *
     * @param n 密钥长度，通常为128, 192或256位
     * @return 生成的AES密钥
     * @throws Exception 如果密钥生成过程中出现错误
     */
    public static SecretKey generateKey(int n) throws Exception {
        // 获取AES密钥生成器的实例
        KeyGenerator keyGenerator = KeyGenerator.getInstance("AES");
        // 初始化密钥生成器，设置密钥长度为n位
        keyGenerator.init(n);
        // 生成并返回AES密钥
        return keyGenerator.generateKey();
    }

    /**
     * 使用AES算法对原始数据进行加密
     *
     * @param originalData 待加密的原始数据
     * @param secretKeyBase64 Base64编码后的密钥
     * @return 加密后的数据，经过Base64编码
     * @throws Exception 如果加密过程中发生错误，则抛出异常
     */
    public static String encrypt(String originalData, String secretKeyBase64) throws Exception {
        // 将Base64编码的密钥转换为字节数组
        byte[] secretKeyBytes = Base64.getDecoder().decode(secretKeyBase64);
        // 使用转换后的密钥字节数组创建一个SecretKey对象
        SecretKey secretKey= new SecretKeySpec(secretKeyBytes,"AES");
        // 获取Cipher对象，用于执行AES加密
        Cipher cipher = Cipher.getInstance("AES");
        // 初始化Cipher对象为加密模式，并传入密钥
        cipher.init(Cipher.ENCRYPT_MODE, secretKey);
        // 对原始数据进行加密，并返回加密后的字节数组
        byte[] encryptedBytes = cipher.doFinal(originalData.getBytes());
        // 将加密后的字节数组转换为Base64编码的字符串，并返回
        return Base64.getEncoder().encodeToString(encryptedBytes);
    }

    /**
     * 使用AES算法解密数据
     *
     * @param encryptedData 已加密的数据，需要被解密
     * @param secretKeyBase64 用于解密的密钥，需先进行Base64解码
     * @return 解密后的字符串
     * @throws Exception 如果解密过程中发生错误，则抛出异常
     */
    public static String decrypt(String encryptedData, String secretKeyBase64) throws Exception {
        // 创建Cipher对象，指定使用AES算法
        Cipher cipher = Cipher.getInstance("AES");

        // 对密钥进行Base64解码，获取原始密钥字节
        byte[] secretKeyBytes = Base64.getDecoder().decode(secretKeyBase64);

        // 使用密钥字节创建SecretKey对象
        SecretKey secretKey = new SecretKeySpec(secretKeyBytes, "AES");

        // 初始化Cipher对象为解密模式，并设置密钥
        cipher.init(Cipher.DECRYPT_MODE, secretKey);

        // 对已加密的数据进行Base64解码，获取加密后的字节数据
        byte[] decodedEncryptedData = Base64.getDecoder().decode(encryptedData);

        // 使用Cipher对象解密数据，获取解密后的字节数据
        byte[] decryptedBytes = cipher.doFinal(decodedEncryptedData);

        // 将解密后的字节数据转换为字符串并返回
        return new String(decryptedBytes);
    }
}
